﻿using HttpApiGateway.Idempotent;
using HttpApiGateway.Interface;
using HttpApiGateway.PlugIn;
using HttpService.Interface;
using RpcClient.Interface;
using RpcHelper;
using System.Collections.Generic;
using System.Reflection;

namespace HttpApiGateway.Service
{
    [RpcClient.Attr.ClassLifetimeAttr(RpcClient.Attr.ClassLifetimeType.单例)]
    internal class IdempotentService : IIdempotentService, IIdempotentHandler
    {
        private readonly IIdempotentConfig _Config;
        private readonly IUnityCollect _Unity;
        private readonly IRouteService _Route;
        private IdempotentType _Type = IdempotentType.关闭;
        private IIdempotent _Idem;
        private readonly IPlugInService _PlugIn;

        public IdempotentService(IIdempotentConfig config, IUnityCollect unity, IRouteService route)
        {
            this._Config = config;
            this._Unity = unity;
            this._Route = route;
        }
        public void Init()
        {
            this._Config.RefreshEvent += _Config_RefreshEvent;
            this._Reset();
        }

    
        private void _Config_RefreshEvent(IIdempotentConfig obj)
        {
            this._Reset();
        }
        public bool CheckIsLimit(string path)
        {
            return  this._Config.CheckIsLimit(path);
        }
        public string GetTokenId(IRoute route, IHttpHandler handler)
        {
            if (this._Type == IdempotentType.关闭)
            {
                return null;
            }
            else if (this._Config.RequestMehod == RequestMehod.Head)
            {
                return handler.Request.Headers[this._Config.ArgName];
            }
            else
            {
               return handler.Request.QueryString[this._Config.ArgName];
            }
          
        }
        private void _Reset()
        {
            if (this._Config.IdempotentType == this._Type)
            {
                return;
            }
            this._Dispose();
            this._Type = this._Config.IdempotentType;
            if (this._Config.IdempotentType == IdempotentType.Token)
            {
                this._Idem = this._Unity.Resolve<ITokenIdempotent>();
            }
            else if (this._Config.IdempotentType == IdempotentType.Key)
            {
                this._Idem = this._Unity.Resolve<IKeyIdempotent>();
            }
            this._PlugIn.Add(new IdempotentPlugIn(this._Idem, this));
            if (this._Config.IdempotentType == IdempotentType.Token && _Config.IsEnableRoute)
            {
                MethodInfo method = this.GetType().GetMethod("_ApplyToken");
                this._Route.RegApi(method, this._Config.TokenRoute);
            }
        }
        private void _Dispose()
        {
            if (this._Type == IdempotentType.Token && _Config.IsEnableRoute)
            {
                _ = this._Route.Remove(this.GetType().GetMethod("_ApplyToken"));
            }
            this._PlugIn.Delete("Idempotent");
        }
        private static string _ApplyToken(ITokenIdempotent token)
        {
            return token.ApplyToken();
        }
    }
}
